﻿using System;
using System.Linq;
using nsadv.Statistic.Domain;
using nsadv.Statistic.Repository;

namespace nsadv.Statistic.Services.Security
{
	public class AddUserError: ApplicationException
	{
		public string UserName { get; private set; }

		public AddUserError(string userName, string message)
			: base(message)
		{
			UserName = userName;
		}
	}

	public class Administration
	{
		protected readonly IRepository<User> Repository;
		protected readonly ITransactionFactory TransactionFactory;

		public Administration(IRepository<User> repository, ITransactionFactory transactionFactory)
		{
			Repository = repository;
			TransactionFactory = transactionFactory;
		}

		public User AddUser(string name, string password)
		{
			User user = null;
			using (var tran = TransactionFactory.BeginTransaction())
			{
				if (Repository.All.Any(x => x.Name == name))
					throw new AddUserError(name, "Пользователь с таким именем уже существует");

				user = new User {Name = name, Password = password};

				Repository.Add(user);
				tran.Commit();
			}
			return user;
		}

		public void MakeUserNone(User user)
		{
			using (var tran = TransactionFactory.BeginTransaction())
			{
				user.Role = UserRole.None;

				user.Place = null;
				user.Advertiser = null;

				Repository.Update(user);

				tran.Commit();
			}
		}

		public void MakeUserRoot(User user)
		{
			using (var tran = TransactionFactory.BeginTransaction())
			{
				user.Role = UserRole.Root;

				user.Place = null;
				user.Advertiser = null;

				Repository.Update(user);

				tran.Commit();
			}
		}

		public void MakeUserAdvertiser(User user, Advertiser advertiser)
		{
			using (var tran = TransactionFactory.BeginTransaction())
			{
				user.Role = UserRole.Advertiser;

				user.Place = null;
				user.Advertiser = advertiser;

				Repository.Update(user);

				tran.Commit();
			}			
		}

		public void MakeUserPlace(User user, Place place)
		{
			using (var tran = TransactionFactory.BeginTransaction())
			{
				user.Role = UserRole.Place;

				user.Place = place;
				user.Advertiser = null;

				Repository.Update(user);

				tran.Commit();
			}				
		}

		public void DeleteUser(User user)
		{
			using (var tran = TransactionFactory.BeginTransaction())
			{
				Repository.Delete(user);
				tran.Commit();
			}				
		}

		public void UpdateUser(User user)
		{
			using (var tran = TransactionFactory.BeginTransaction())
			{
				Repository.Update(user);
				tran.Commit();
			}
		}

		public IQueryable<User> AllUsers { get { return Repository.All; } }
	}
}
